from django.shortcuts import render
from django.views import View
from django.conf import settings
from django.http import JsonResponse
from django_redis import get_redis_connection
from django.contrib.auth import login

from QQLoginTool.QQtool import OAuthQQ
import json,re

from users.models import User
from .models import OAuthQQUser
from meiduo_mall.utils.secret import SecretOauth
from carts.utils import merge_cart_cookie_to_redis
# Create your views here.

# QQ登陆接口一：获取扫码页面url
class QQURLView(View):

    def get(self, request):
        # 1、提取参数
        next = request.GET.get('next')
        # 2、校验参数
        # 3、业务数据处理 —— 获取扫码url
        # (1)、实例化OAuth对象
        oauth = OAuthQQ(
            client_id=settings.QQ_CLIENT_ID,
            client_secret=settings.QQ_CLIENT_SECRET,
            redirect_uri=settings.QQ_REDIRECT_URI,
            state=next # 用于传递一个请求路径，表示完整qq登陆成功之后前端跳转回美多页面
        )
        # (2)、调用对象get_qq_url函数获取链接
        login_url = oauth.get_qq_url()
        # 4、构建响应
        return JsonResponse({
            'code': 0,
            'errmsg': 'ok',
            'login_url': login_url
        })


class QQUserView(View):

    # QQ登陆接口二：获取openid
    def get(self, request):
        # 1、提取参数
        code = request.GET.get('code') # qq服务器在用户扫码登陆之后返回给用户的
        # 2、校验参数
        # 3、业务数据处理 —— 校验code获取openid
        # TODO: =========获取openid===========
        # (1)、实例化OAuth对象
        oauth = OAuthQQ(
            client_id=settings.QQ_CLIENT_ID,
            client_secret=settings.QQ_CLIENT_SECRET,
            redirect_uri=settings.QQ_REDIRECT_URI,
            state=None
        )

        try:
            # (2)、校验code，获取access_token
            access_token = oauth.get_access_token(code)
            # (3)、校验access_token，获取openid
            openid = oauth.get_open_id(access_token)
        except Exception as e:
            print(e)
            # qq登陆身份校验失败
            return JsonResponse({'code': 400, 'errmsg': 'qq身份验证失败'})

        # TODO: =========判定openid是否绑定过账号===========
        # 4、构建响应
        # (1)、根据openid查询模型类OAuthQQUser
        try:
            oauth_user = OAuthQQUser.objects.get(openid=openid)
        except OAuthQQUser.DoesNotExist as e:
            # 抛出异常说明,构建响应(未绑定) —— 加密openid构建响应返回
            # (2)、加密openid构建响应返回
            access_token = SecretOauth().dumps({'openid': openid}) # 密文
            return JsonResponse({'code': 400, 'errmsg': '未绑定', 'access_token': access_token})

        # (3)、构建响应(绑定)
        # 状态保持
        login(request, oauth_user.user)
        # 设置cookie
        response = JsonResponse({'code': 0, 'errmsg': 'ok'})
        response.set_cookie('username', oauth_user.user.username, max_age=3600*14*24)
        # TODO: 合并购物车
        response = merge_cart_cookie_to_redis(request, response)
        return response


    # QQ登陆接口三：绑定账号
    def post(self, request):
        # 1、提取参数
        data = json.loads(request.body.decode())
        mobile = data.get('mobile')
        password = data.get('password')
        sms_code = data.get('sms_code')
        access_token = data.get('access_token') # 加密的openid字典: {"openid": "xxxxxx"}

        # 2、校验参数
        # 2.1、必要性校验
        if not all([mobile, password, sms_code, access_token]):
            return JsonResponse({'code': 400, 'errmsg': '缺少必要参数'})
        # 2.2、格式校验/约束校验
        if not re.match('1[3-9]\d{9}$', mobile):
            return JsonResponse({
                'code': 400,
                'errmsg': '手机号格式有误'
            })
        if not re.match('^[a-zA-Z0-9_]{8,20}$', password):
            return JsonResponse({
                'code': 400,
                'errmsg': '密码格式有误'
            })
        # 2.3、业务性校验
        conn = get_redis_connection('verify_code')
        sms_code_from_redis = conn.get('sms_%s'%mobile)
        if not sms_code_from_redis:
            return JsonResponse({'code': 400, 'errmsg': '短信验证码失效'})
        if sms_code != sms_code_from_redis.decode():
            return JsonResponse({'code': 400, 'errmsg': '验证码有误'})
        # TODO: openid解密 —— 业务校验
        data = SecretOauth().loads(access_token) # {"openid": "xxx"} or None
        if data is None:
            # openid解密失败 —— 有可能伪造
            return JsonResponse({'code': 400, 'errmsg': 'openid无效'})
        openid = data.get('openid')

        # 3、业务数据处理 —— 绑定账号
        try:
            user = User.objects.get(mobile=mobile)
        except User.DoesNotExist as e:
            # 用户未注册美多账号
            # (1)、新建User对象
            user = User.objects.create_user(
                username=mobile, # 此处我们把手机号作为用户的默认用户名
                mobile=mobile,
                password=password
            )
            # (2)、绑定账号
            OAuthQQUser.objects.create(
                user=user,
                openid=openid
            )
        else:
            # 用户注册过美多账号 —— 直接绑定
            # (1)、校验密码
            if not user.check_password(password):
                return JsonResponse({'code': 400, 'errmsg': '用户名或密码有误'})
            # (2)、绑定账号
            OAuthQQUser.objects.create(
                user=user,
                openid=openid
            )

        # 4、构建响应
        # 状态保持
        login(request, user)
        response = JsonResponse({'code': 0, 'errmsg': 'ok'})
        # cookie设置username作页面展示
        response.set_cookie('username', user.username, max_age=3600*24*14)
        # TODO: 合并购物车
        response = merge_cart_cookie_to_redis(request, response)
        return response












